package com.my.config;

import com.netflix.discovery.converters.Auto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import java.security.KeyPair;

/**
 * @Author coderMy
 * @Date 2021/3/30
 */
@Configuration
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private AuthenticationManager authenticationManager;


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("cloud-ego")
                .secret(passwordEncoder.encode("cloud-ego"))
                .scopes("all")
                .authorizedGrantTypes("password")
                .accessTokenValiditySeconds(86400)
                .and()
                .withClient("client")
                .secret(passwordEncoder().encode("client-secret"))
                .scopes("read")
                .authorizedGrantTypes("client_credentials") // 客户端授权 一般可以用在系统之间自发远程调用 不是用户驱动的
                .accessTokenValiditySeconds(Integer.MAX_VALUE) // 可以用66年
                .redirectUris("https://www.baidu.com");
    }


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore)
                .accessTokenConverter(jwtAccessTokenConverter)
                .authenticationManager(authenticationManager);
    }


    /**
     * JWT转换器,JWT非对称加密,私钥加密,公钥解
     * 私钥加密的内容,公钥始终可以解开.公钥放在每个服务里,Oauth拦截解析JWT时用公钥解JWT
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){

        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        //私钥存储地址
        ClassPathResource classPathResource = new ClassPathResource("cxs-jwt.jks");
        //根据私钥,创建钥匙工厂
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource,"cxs123".toCharArray());
        //创建钥匙
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair("cxs-jwt");
        //设置钥匙
        jwtAccessTokenConverter.setKeyPair(keyPair);
        return jwtAccessTokenConverter;
    }

    /**
     * token以JWT方式生成
     * 需要JWT转换器
     * @return
     */
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    /**
     * 密码加密器
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
